﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace RobotGameData
{
    public abstract class Character
    {
        #region Properties

        #region "Graphics Data"
        // tên texture
        private string assetName;
        public string AssetName
        {
            get { return assetName; }
            set { assetName = value; }
        }
        // texture
        private Texture2D texture;
        public Texture2D Texture
        {
            get { return texture; }
            set { texture = value; }
        }
        
        #endregion

        // poistion
        private Vector2 position;
        public Vector2 Position
        {
            get { return position; }
            set
            {
                position = value;
                Bounds = new Rectangle((int)value.X, (int)value.Y, (int)FrameSize.X, (int)FrameSize.Y);
            }
        }
        public float RotationAngle { get; set; }
        public Vector2 Origin { get; set; }
        public Vector2 Scale { get; set; }
        public SpriteEffects Orientation { get; set; }
        public bool IsVisible { get; set; }
        public Rectangle Bounds { get; set; }
    

        #region Frame Data

        protected float timer = 0;
        protected int currentFrame = 0;
        protected int totalFrames = -1;
        private Rectangle? sourceRectangle = null;

        public Vector2 FrameSize { get; set; }
        public bool IsAnimating { get; set; }
        public float FrameLength { get; set; }
        public int MaxFramesPerDirection { get; set; }
        public Vector2 TilePosition { get; set; }
        public Direction Direction { get; set; }
        public float Speed { get; set; }
        public Vector2 LastMovement { get; set; }
        #endregion

        protected int SpritesPerRow
        {
            get
            {
                return (int)(Texture.Width / FrameSize.X);
            }
        }

        protected int SpritesPerColumn
        {
            get
            {
                return (int)(Texture.Height / FrameSize.Y);
            }
        }

        public Rectangle? SourceRectangle
        {
            get
            {
                if (currentFrame >= 0)
                {
                    int x = (int)((currentFrame % SpritesPerRow) * FrameSize.X);
                    int y = (int)((currentFrame / SpritesPerRow) * FrameSize.Y);
                    int w = (int)FrameSize.X;
                    int h = (int)FrameSize.Y;

                    sourceRectangle = new Rectangle(x, y, w, h);
                }

                return sourceRectangle;
            }
            set
            {
                sourceRectangle = value;
            }
        }

        

        const float atDestinationLimit = 5f;

        protected Vector2 directions;
        public Vector2 Directions
        {
            get { return directions; }
            set { directions = value; }
        }

        protected bool moving;
        public bool Moving
        {
            get { return moving; }
            set { moving = value; }
        }

        const float moveSpeed = 100f;
        public static float MoveSpeed
        {
            get { return moveSpeed; }
        }
        private Vector2 destination;
        public Vector2 Destination
        {
            get { return destination; }
        }
        private Vector2 location;
        public Vector2 Location
        {
            get { return location; }
        }

        private WaypointList waypoints;
        public WaypointList Waypoints
        {
            get { return waypoints; }
        }

        public float DistanceToDestination
        {
            get { return Vector2.Distance(position, destination); }
        }

        public bool AtDestination
        {
            get { return DistanceToDestination < atDestinationLimit; }
        }

        #endregion

        #region Constructor

        public Character()
		{
			assetName = "";
			Texture = null;
			Position = Vector2.Zero;
			SourceRectangle = null;
			RotationAngle = 0f;
			Origin = Vector2.Zero;
			Orientation = SpriteEffects.None;
			IsVisible = true;

            FrameSize = new Vector2(64f, 64f);
            IsAnimating = true;
            FrameLength = 0.05f;


            location = Vector2.Zero;
            destination = position;
            waypoints = new WaypointList();
		}

        #endregion

        #region Methods

        public virtual void LoadContent(ContentManager content, string assetName)
        {
            this.assetName = assetName;
            Texture = content.Load<Texture2D>(assetName);            

            waypoints.LoadContent(content);

        }

        public void Update(GameTime gameTime, Camera camera)
        {
            if (!IsAnimating) return;

            if (totalFrames == -1) totalFrames = SpritesPerRow * SpritesPerColumn;

            timer += (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (timer >= FrameLength)
            {
                timer = 0f;

                currentFrame = ((currentFrame + 1) % MaxFramesPerDirection) + ((int)Direction * MaxFramesPerDirection);
            }

            //Update(gameTime);
        }

        public void Update(GameTime gameTime)
        {
            float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (moving)
            {
                // If we have any waypoints, the first one on the list is where 
                // we want to go
                if (waypoints.Count >= 1)
                {
                    destination = waypoints.Peek();
                }

                // If we’re at the destination and there is at least one waypoint in 
                // the list, get rid of the first one since we’re there now
                if (AtDestination && waypoints.Count >= 1)
                {
                    waypoints.Dequeue();
                }

                if (!AtDestination)
                {
                    //directions = -(location - destination);
                    directions = -(position - destination);
                    //This scales the vector to 1, we'll use move Speed and elapsed Time 
                    //to find the how far the tank moves
                    directions.Normalize();
                    //location = location + (Directions *
                    //    MoveSpeed * elapsedTime);
                    position = position + (Directions *
                        MoveSpeed * elapsedTime);

                }
            }
        }

        public void Collision()
        {
            Position -= LastMovement;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            //waypoints.Draw(spriteBatch);

            if (IsVisible && Texture != null)
            {
                Rectangle destRect = new Rectangle((int)Position.X, (int)Position.Y, (int)FrameSize.X, (int)FrameSize.Y);
                spriteBatch.Draw(Texture, destRect, SourceRectangle, Color.White, MathHelper.ToRadians(RotationAngle), Origin, SpriteEffects.None, 0f);
            }
        }
   

        #endregion
    }
}
